<?php
function shift($arr){
	if(is_array($arr)){
		return array_shift($arr);
	}else{
		return false;
	}
}

function quote($data, $like=false){
	if (is_null($data) || ((string) $data == 'NULL')){return 'NULL';}
	if (is_array($data)){
		$ret =  array();
		foreach ($data as $key => $value){
			if (is_array($value)){
				$ret[$key] = quote($value, $like);
			}
			elseif (!is_numeric($key)){
				if (is_null($value) || ((string) $value == 'NULL')){$ret[$key] = 'NULL';}
				else {
					$ret[$key] = quote($value, $like);
				}
			}
			else {//don't alter numeric indexes
				$ret[] = $value;
			}
		}
		return $ret;
	}
	if ($like === 'start'){return "'%".mysql_escape_string($data)."'";}
	elseif ($like === 'end'){return "'".mysql_escape_string($data)."%'";}
	elseif ($like){return "'%".mysql_escape_string($data)."%'";}
	return "'".mysql_escape_string($data)."'";
}

function _get_caller($level=1){
	if (function_exists('debug_backtrace')){
		$bt = debug_backtrace();
		// echo '<pre>'; print_r($bt);echo "</pre>\r\n";exit;
		if ($a = $bt[$level]){
			$caller = '';
			if (!$a['class'] && ($a['function'] == 'debug') && $bt[$level+1]){$a = $bt[$level+1];}
			if ($a['class']){$caller .= $a['class'].$a['type'];}
			if ($a['function']){$caller .= $a['function'];}
			
			$in = substr($a['file'], strrpos($a['file'], DIRECTORY_SEPARATOR)+1);
			$line = $a['line'];
			$caller .= sprintf(' in %s @ %04d', $in, $line);
			return $caller;
		}
	}
	return '';
}

function print_var($in, $return=false, $simple=true, $recursive_level=0, $level=0){
	if (!$_SERVER['SERVER_PORT']){
		if (is_array($in) || is_object($in)){print_r($in);}
		else{var_dump($in);}
		return;
	}
	else{
		static $style_dumped = false;
		if (!$style_dumped){
			$style_dumped = true;
?>
<style type="text/css">
	.debug_container{
		margin: 0px;
		padding: 1px;
		border: 1px solid #000000;
		overflow: auto;
		color: #000000;
		background-color: #FFFFFF;
		text-align: left;
		font: bold 12px Verdana, Geneva, Arial, Helvetica, sans-serif;
	}
	.debug_container .box{
		margin: 0px;
		padding: 0px;
		margin-left: 25px;
		font: inherit;
	}
	.debug_container .caller{
		float: right;
		margin-top: 2px;
		font-size: 10px;
		font-weight: normal;
		font-style: italic;
	}
</style>
<?
	}
	}
	$key_color = '#990033';
	$type_colors = array(
		// scalar
		'boolean' => '#0000FF'
		,'integer' => '#008000'
		,'double' => '#008000'
		,'string' => '#008080'
		// compound
		,'array' => '#FF3300'
		,'object' => '#800080'
		// special
		,'resource' => '#993366'
		,'null' => '#000066'
	);

	if (!$level){
		if ($return){
			if ($s = ob_get_level()){ob_end_flush();}
			ob_start();
		}
		echo '<pre class="debug_container">', "\r\n";
	}
	/***********************************************************/
	$type = strtolower(gettype($in));

	switch ($type){
		case "array":
		case "object":
			printf(
				'<span style="color: %s;">%s%s: </span>'
				,$type_colors[$type]
				,ucfirst($type)
				,($type == 'object') ? ' ('.get_class($in).')' : ''
			);
			echo "(\r\n";
			// printf('<div style="margin: 0px; padding: 0px; margin-left: %dpx;">', ($level+1)*15);
			printf('<div class="box">');
			foreach ($in as $key => $value){
				// echo_char(' ', $level*4, true);
				str_repeat(' ', $level*4);
				printf(
					'[<span style="color: %s;">%s</span>] => '
					,$key_color
					,htmlspecialchars($key)
				);
				//echo "$recursive_level > $level<br>\r\n";
				$s_type = strtolower(gettype($value));
				// if (($in === $GLOBALS) /* && ($key == 'GLOBALS') */){
				if (is_array($in) && isset($in['GLOBALS']) && ($key == 'GLOBALS')){
					printf(
						'<span style="color: %s;">%s</span> ...'
						,$type_colors[$s_type]
						,'*Recursion'
					);
					echo "\r\n";
				}
				elseif (!$recursive_level || !in_array($s_type, array('array', 'object')) || (($recursive_level > $level) && in_array($s_type, array('array', 'object')))){print_var($value, false, $simple, $recursive_level, $level+1);}
				else{
					printf(
						'<span style="color: %s;">%s</span> ...'
						,$type_colors[$s_type]
						,htmlspecialchars(ucfirst($s_type))
					);
					echo "\r\n";
				}
			}
			echo "</div>)\r\n";
		break;
		case "resource":
			if ($simple){
				printf('<span style="color: %s;">%s</span>', $type_colors[$type], $in);
				echo "\r\n";
			}
			else{
				printf(
					'<span style="color: %s;">%s: </span>'
					,$type_colors[$type]
					,ucfirst($type)
				);
				echo $in."\r\n";
			}
		break;
		case "boolean":
			if ($simple){
				printf('<span style="color: %s;">%s</span>', $type_colors[$type], ($in) ? 'true' : 'false');
				echo "\r\n";
			}
			else{
				printf(
					'<span style="color: %s;">%s: </span>'
					,$type_colors[$type]
					,ucfirst($type)
				);
				echo (($in) ? 'true' : 'false')."\r\n";
			}
		break;
		case "null":
			printf('<span style="color: %s;">%s</span>', $type_colors[$type], 'NULL');
			echo "\r\n";
		break;
		case "unknown type":
			printf('<span style="color: %s;">%s</span>', $type_colors[$type], $in);
			echo "\r\n";
		break;
		default:
			if ($simple){
				printf('<span style="color: %s;">%s</span>', $type_colors[$type], htmlspecialchars($in));
				echo "\r\n";
			}
			else{
				printf(
					'<span style="color: %s;">%s: </span>'
					,$type_colors[$type]
					,ucfirst($type)
				);
				echo htmlspecialchars($in)."\r\n";
			}
		break;
	}
	//echo '<span style="clear: both; width: 1px; height: 1px; font-size: 1px;">.</span>'."\r\n";
	/***********************************************************/
	if (!$level){
		if ($c = _get_caller(1)){
			printf('<span class="caller">Call: %s</span><span style="clear: both; font-size: 10px; float: none; color: #FFFFFF;">.</span>', $c);
		}
		echo '</pre>'/* , "\r\n" */;
		if ($return){
			$r = ob_get_clean();
			if ($s){ob_start();}
			return $r;
		}
	}
}

function print_var_U($in, $label = ''){
	echo '<pre style="margin: 0px; padding: 1px; border: 1px solid #000; text-align: left; font: bold 12px monospace, Verdana, Geneva, Arial, Helvetica, sans-serif;">', "\r\n";
	if ($label){echo "DEBUG [<strong>$label</strong>]: ";}
	echo "string (".($l = strlen($in)).")";
	echo("\n=======0====1====2====3====4====5====6====7====8====9====10===11===12===13===14===15==");
	for ($i=0;$i<$l;$i++){
		if (($i % 16) == 0){printf("\n[%04d]", ($i/16));}
		printf(" %-4u", ord($in{$i}));
	}
	echo("\n======================================================================================\n");
	echo '</pre>', "\r\n";
}
function print_var_X($in, $label = ''){
	echo '<pre style="margin: 0px; padding: 1px; border: 1px solid #000; text-align: left; font: bold 12px monospace, Verdana, Geneva, Arial, Helvetica, sans-serif;">', "\r\n";
	if ($label){echo "<strong>$label</strong>: ";}
	echo "string (".($l = strlen($in)).")";
	echo("\n=======0====1====2====3====4====5====6====7====8====9====10===11===12===13===14===15==");
	for ($i=0;$i<$l;$i++){
		if (($i % 16) == 0){printf("\n[%04d]", ($i/16));}
		printf(" 0x%02X", ord($in{$i}));
	}
	echo("\n======================================================================================\n");
	echo '</pre>', "\r\n";
}
function print_var_B($in, $label = ''){
	echo '<pre style="margin: 0px; padding: 1px; border: 1px solid #000; text-align: left; font: bold 12px monospace, Verdana, Geneva, Arial, Helvetica, sans-serif;">', "\r\n";
	if ($label){echo "<strong>$label</strong>: ";}
	echo "string (".($l = strlen($in)).")";
	echo("\n=======0========1========2========3========4========5========6========7========8========9========10=======11=======12=======13=======14=======15=======");
	for ($i=0;$i<$l;$i++){
		if (($i % 16) == 0){printf("\n[%04d]", ($i/16));}
		printf(" %08b", ord($in{$i}));
	}
	echo("\n=======================================================================================================================================================");
	echo '</pre>', "\r\n";
}
function print_var_S($in, $label = ''){
	echo '<pre style="margin: 0px; padding: 1px; border: 1px solid #000; text-align: left; font: bold 12px monospace, Verdana, Geneva, Arial, Helvetica, sans-serif;">', "\r\n";
	if ($label){echo "<strong>$label</strong>: ";}
	var_dump($in);
	echo '</pre>', "\r\n";
}

function print_array($in){
	return print_var($in, $return=false, $simple=true, $recursive_level=0, $level=0);
}

function print_code($code, $highlight=NULL, $options=NULL){
	echo '<pre style="margin: 1px; padding: 2px; border: 1px solid #000; text-align: left; font: 12px Verdana, Geneva, Arial, Helvetica, sans-serif; width: 99%;height: 250px; overflow: auto; clear: both;">', "\r\n";
	$bg_color = '#33CCFF';
	$color = '';
	if ($options){
		if (is_array($options)){
			if (isset($options['bg_color'])){$bg_color = $options['bg_color'];}
			if (isset($options['bgcolor'])){$bg_color = $options['bgcolor'];}
			if ($options['color']){$color = $options['color'];}
		}
	}
	if (is_array($highlight)){
		$first_key = array_keys($highlight);
		$first_key = $first_key[0];
		// single hl
		if (!is_array($highlight[$first_key])){$highlight = array($highlight);}
	}
	else{$highlight = array();}
	// color anything?
	if ($highlight && ($bg_color || $color)){
		// sort array
		$_highlight = array();
		for ($i=0;$i<count($highlight);$i++){
			// print_var($highlight[$i]);
			$start = (isset($highlight[$i]['start'])) ? $highlight[$i]['start'] : $highlight[$i][0];
			if ($highlight[$i]['end']){$len = $highlight[$i]['end'] - $start;}
			else{$len = ($highlight[$i]['len']) ? $highlight[$i]['len'] : ((isset($highlight[$i]['start'])) ? $highlight[$i][0] : $highlight[$i][1]);}
			if ($len > 0){$_highlight[$start] = $len;}
			// print_var("$start / $len");
		}
		if ($_highlight){
			krsort($_highlight);
			// print_var($_highlight);
			// mark zones for hl
			$hl_start = '<span style="';
			if ($color){$hl_start .= "color: $color;";}
			if ($bg_color){$hl_start .= "background-color: $bg_color;";}
			$hl_start .= '" title="Start: %u, Len: %u">';
			$hl_end = '</span>';
			$mark_start = 'MARK_START_';
			$mark_end = 'MARK_END';
			foreach ($_highlight as $start => $len){
				// apply end mark
				$code = substr_replace($code, $mark_end, $start+$len, 0);
				// apply start mark
				$code = substr_replace($code, $mark_start.$start, $start, 0);
			}
			$code = htmlspecialchars($code);
			if (preg_match_all('/'.$mark_start.'([0-9]+)/m', $code, $m)){
				$m = $m[1];
				krsort($m);
				// print_var($m);
				// $code = str_replace($m, $hl_start, $code);
				foreach ($m as $start){
					$code = str_replace($mark_start.$start, sprintf($hl_start, $start, $_highlight[$start]), $code);
				}
			}
			$code = str_replace($mark_end, $hl_end, $code);
			echo "$code\r\n";
		}
	}
	else{echo htmlspecialchars($code)."\r\n";}
	if ($c = _get_caller(1)){
		printf('<span style="float: right; font-size: 10px; font-weight: normal; font-style: italic; margin-top: 2px;">Call: %s</span><div style="clear: both; font-size: 1px;">.</div>', $c);
	}
	echo '</pre>', "\r\n";
}

function generate_code($len=10){
	$str = 'abcdefghijklmnoprstuvxyzABCDEFGHIJKLMNOPRSTUVXYZ0123456789';
	$code = '';
	for($i=0;$i<$len;$i++){
		$code.= $str[rand(0, strlen($str)-1)];
	}
	return $code;
}
?>